<?php
	require_once(dirname(__FILE__)."/incluir.php");
	// Como vai precisar de um valor único de GuardaDados em todos os momentos que gerar um viale, ele será um singleton
	class GeraDados
	{
		public $tabelas;
		public $erros;
		public $tabela_atual;
		private $sqlController;
		
		public function __construct($tabela_atual = null, $sqlController = null)
		{
			$this->tabela_atual = $tabela_atual;
			
			if($sqlController == null) // se não foi passado uma instancia de um controlador de banco de dados, usa o de mysql
			{
				$this->sqlController = new MySQLController();
			}
			else
			{
				$this->sqlController = $sqlController;
			}
			
			$this->get_tabelas();
		}
		
		// Funções auxiliares (funções privadas/protected)
		
		private function salva_template($filename, $valor)
		{
			$path = dirname(__FILE__)."/../$this->tabela_atual/$filename";
			file_put_contents($path, $valor);
		}
		
		// Função auxiliar para copiar o diretório chamado viale para o diretorio com o nome da tabela
		// Essa função também renomeia o arquivo Cliente.php e o nome da classe Cliente
		private function copia_diretorio($guarda_dados)
		{
			$source_dir = dirname(__FILE__)."/../viale";
			$dest_dir = dirname(__FILE__)."/../$this->tabela_atual";
			
			// Se o diretório não existe, cria o diretório
			if(!file_exists($dest_dir))
			{
				mkdir($dest_dir);
			}
			FileController::copy_directory($source_dir, $dest_dir); // Copia os dois diretórios

			$novo_controller = $guarda_dados->classe."Controller"; // Nome do novo controller
			$novo_model = $guarda_dados->classe."Model"; // Nome do novo model
			
			rename("$dest_dir/ClienteController.php", "$dest_dir/$novo_controller.php"); // Renomeia o arquivo com o Controller
			rename("$dest_dir/ClienteModel.php", "$dest_dir/$novo_model.php"); // Renomeia o arquivo com o Model
			
			$paths = array(
				// Vai substituir ClienteController e ClienteModel nos arquivos com o Controller e com o Model
				"$dest_dir/$novo_controller.php", "$dest_dir/$novo_model.php",
				// Vai substituir ClienteController e ClienteModel nos arquivos do viale
				"$dest_dir/visualizar.php", "$dest_dir/inserir.php", "$dest_dir/alterar.php", "$dest_dir/index.php", "$dest_dir/excluir.php"
			);
			
			$nome_controller = '$'.$guarda_dados->tabela.'_controller';
			// Substitui ClienteController e ClienteModel em todos os arquivos necessários
			FileController::substitui_palavras($paths, array('ClienteController', 'ClienteModel','$controller'), array($novo_controller, $novo_model, $nome_controller));
		}
		
		// Passando só o nome do arquivo, copia do diretorio de viale para o destino correto
		private function copia_arquivo($source, $dest)
		{
			$source_full_path = dirname(__FILE__)."/../viale/$source";
			$dest_dir = dirname(__FILE__)."/../$this->tabela_atual";
			// Se o diretório não existe, cria o diretório
			if(!file_exists($dest_dir))
			{
				mkdir($dest_dir);
			}
			$dest_full_path = "$dest_dir/$dest";
			copy($source_full_path, $dest_full_path); // Copia o arquivo $source para o arquivo $dest
		}
		
		private function append_output(&$output,$value)
		{	
			$output .= $value;
			$output .= "\n";
		}
		
		private function get_tabelas()
		{
			$this->tabelas = $this->sqlController->get_tables_from_database();
		} 
		
		// Funções para as ações
		
		public function tabela_passada_valida($get)
		{
			$site = new Site; // instancia site para usar a função abaixo
			if(!$site->checa_param_passado($_GET, 'tabela'))
			{
				return false;
			}
			// Se o usuário passou uma tabela que não existe no banco de dados retorna false
			else if(!in_array($_GET['tabela'], $this->tabelas))
			{
				return false;
			}
			return true;
		}
		
		// Gera o valor do atributo tabelas_excluir de guarda_dados, com os valores de tabelas_excluir_nomes e tabelas_excluir_ids
		private function set_tabelas_excluir(&$guarda_dados, $tabelas_excluir_nomes, $tabelas_excluir_ids)
		{
			$tabelas_excluir_nomes_arr = explode(',',$tabelas_excluir_nomes); 
			$tabelas_excluir_ids_arr = explode(',',$tabelas_excluir_ids);
			 
			foreach($tabelas_excluir_nomes_arr as $index => $tabela_nome)
			{
				$tabela_id = $tabelas_excluir_ids_arr[$index];
				$guarda_dados->tabelas_excluir[$tabela_nome] = $tabela_id;
			}
		}
		
		// Guarda os dados preenchidos em criar_viale.php na unica instancia de GuardaDados
		private function set_dados_gerais(&$guarda_dados, $post)
		{
			extract($post); // tranformo os valores de post em variaveis (exemplo $limit = $post['limit'])
			$lista_nome_campos = array('limit', 'range', 'offset_default', 'referencia', 'campos_valores_default','campos_paginas',
				'campos_multiplos', 'tabelas_excluir', 'mensagem_sucesso_inserir','mensagem_erro_inserir',
				'mensagem_sucesso_alterar', 'mensagem_erro_alterar', 'mensagem_sucesso_excluir', 'mensagem_erro_excluir',
				'mensagens_erro_campos', 'mensagens_erro_campos_not_empty', 'tipos_campos', 'valores_campos');
			// Coloca os valores que interessam, ou seja, que estão no array $lista_nome_campos, do $post em $guarda_dados
			foreach($lista_nome_campos as $nome_campo)
			{
				$guarda_dados->$nome_campo = $post[$nome_campo];
			}
			$this->set_tabelas_excluir($guarda_dados, $tabelas_excluir_nomes, $tabelas_excluir_ids);
		}
		
		private function gera_campos_valores_default($guarda_dados)
		{
			$first = true;
			$campos_valores_default = ""; // ficará da forma: "campo1" => "valor_default1", "campo2" => "valor_default2", etc. 
			foreach($guarda_dados->fields as $index => $field)
			{
				$valor_default = $guarda_dados->campos_valores_default[$index]; // Pega o valor default do campo
				if($valor_default == "") continue; // Se não tiver um valor default passa para o próximo campo
				// Se for um número coloca aspas entre o valor
				$valor_default = (is_numeric($valor_default)) ? $valor_default : '"'.$valor_default.'"';
								
				if($first)
				{
					$campos_valores_default .= " \"$field\" => $valor_default";
					$first = false;
				}
				else
				{
					$campos_valores_default .= ", \"$field\" => $valor_default";
				}
			}
			return $campos_valores_default;
		}
		
		private function gera_campos_paginas($guarda_dados)
		{
			$first = true;
			$campos_paginas = ""; // ficará da forma: "campo1" => array('pag1', 'pag2'), "campo2" => array('pag3'), etc. 
			foreach($guarda_dados->fields as $index => $field)
			{
				$paginas = $guarda_dados->campos_paginas[$index]; // Pega a string com as páginas separadas por virgula
				if(!empty($paginas)) // Se $paginas for vazio, deve ficar na forma: "campo" => array() e assim não entrará nesse if
				{
					$paginas = "'".str_replace(",","','",$paginas)."'"; // Coloca aspas simples entre os nomes das páginas
				}
				if($first)
				{
					$campos_paginas .= " \"$field\" => array($paginas)";
					$first = false;
				}
				else
				{
					$campos_paginas .= ",\n\t\t \"$field\" => array($paginas)";
				}
			}
			return $campos_paginas;
		}
		
		private function gera_campos_multiplos($guarda_dados)
		{
			$first = true;
			$campos_multiplos = ""; // ficará da forma: 'compo1','campo2','campo3', etc. 
			if(is_array($guarda_dados->campos_multiplos)) // Se tiver algum campo múltiplo
			{
				foreach($guarda_dados->fields as $index => $field)
				{
					$is_campo_multiplo = $guarda_dados->campos_multiplos[$index];
					if($first && $is_campo_multiplo)
					{
						$campos_multiplos .= " \"$field\"";
						$first = false;
					}
					else if($is_campo_multiplo)
					{
						$campos_multiplos .= ", \"$field\"";
					}
				}
			}
			return $campos_multiplos;
		}
		
		private function gera_tabelas_excluir($guarda_dados)
		{
			$first = true;
			$tabelas_excluir = ""; // ficará da forma: "tabela1" => "id1", "tabela2" => "id2", etc. 
			foreach($guarda_dados->tabelas_excluir as $tabela_nome => $tabela_id)
			{
				if(empty($tabela_nome)) continue; // Se não for um valor concreto de uma tabela, não adiciona
				if($first)
				{
					$tabelas_excluir .= "\"$tabela_nome\" => \"$tabela_id\"";
					$first = false;
				}
				else
				{
					$tabelas_excluir .= ", \"$tabela_nome\" => \"$tabela_id\"";
				}
			}
			return $tabelas_excluir;
		}
		
		private function gera_mensagens_erro_campos($guarda_dados)
		{
			$mensagens_erro_campos = '';
			$first = true;
			foreach($guarda_dados->fields as $index => $field)
			{
				$mensagem_erro = $guarda_dados->mensagens_erro_campos[$index];
				$mensagem_erro_not_empty = $guarda_dados->mensagens_erro_campos_not_empty[$index];
				if($first)
				{
					$mensagens_erro_campos = "'$field' => '$mensagem_erro', \n\t\t'$field"."_not_empty' => '$mensagem_erro_not_empty'";
					$first = false;
				}
				else
				{
					$mensagens_erro_campos .= ",\n\t\t'$field' => '$mensagem_erro', \n\t\t'$field"."_not_empty' => '$mensagem_erro_not_empty'";
				}
			}
			return $mensagens_erro_campos;
		}
		
		// função auxiliar a função gera_campos_varios_valores que vai montar o array de valores em texto
		private function adiciona_valores_campos_varios_valores(&$output, $valores_string)
		{
			$first = true;
			$valores = split(',',$valores_string);
			for($i = 0; $i < count($valores); $i += 2 )
			{
				// Faz com que cada valor seja um array aonde o primeiro elemento é o valor mesmo e o segundo é o valor a ser mostrado
				$valor = is_numeric($valores[$i]) ? $valores[$i] : "'".$valores[$i]."'"; // Se for um texto será entre aspas
				$valor_mostrado = is_numeric($valores[$i+1]) ? $valores[$i+1] : "'".$valores[$i+1]."'"; // Se for um texto será entre aspas
				$valor_string = "array($valor, $valor_mostrado)";
				if($first)
				{
					$output .= "$valor_string";
					$first = false;
				}
				else
				{
					$output .= ",$valor_string";
				}	
			}
		}		
		
		// Vai gerar um array, aonde cada elemento é do formato: 'nome_campo' => array('valor1', 'valor2', 'valor3')
		private function gera_campos_varios_valores($guarda_dados, &$selects, &$checkboxes, &$radios)
		{
			foreach($guarda_dados->fields as $index => $field)
			{
				if($guarda_dados->tipos_campos[$index] != 'Nenhum') // Se é para salvar em alguma string
				{
					$tipo = $guarda_dados->tipos_campos[$index]; // tipo do campo
					$valores = $guarda_dados->valores_campos[$index]; // Os valores separados por vírgula do campo
					switch($tipo)
					{
						case 'select':
							$selects .= "'$field' => array(";
							$this->adiciona_valores_campos_varios_valores($selects, $valores);						
							$selects .= "),";
							break;
						case 'checkbox':
							$checkboxes .= "'$field' => array(";
							$this->adiciona_valores_campos_varios_valores($checkboxes, $valores);						
							$checkboxes .= "),";
							break;
						case 'radio':
							$radios .= "'$field' => array(";
							$this->adiciona_valores_campos_varios_valores($radios, $valores);						
							$radios .= "),";
							break;
						default:
							break;
					}
				}
			}
		}
		
		// Cria o novo arquivo dados.php e atualiza no novo diretorio da entidade
		private function gera_dados($guarda_dados)
		{
			// Pega o conteudo do arquivo auxiliar gera_dados.php (uma copia de qualquer arquivo dados.php)
			$conteudo_arquivo = file_get_contents("gera_dados.php");
			
			// O modelo de gera_dados.php é ter os valores na forma: nome_do_atributo_valor para ser substituido pelo atributo de guarda_dados
			$conteudo_arquivo = str_replace("tabela_valor", $guarda_dados->tabela, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("nome_entidade_valor", $guarda_dados->nome_entidade, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("sufixo_valor", $guarda_dados->sufixo, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("limit_valor", $guarda_dados->limit, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("range_valor", $guarda_dados->range, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("offset_default_valor", $guarda_dados->offset_default, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("referencia_valor", $guarda_dados->referencia, $conteudo_arquivo);
			// Parte das mensagens
			$conteudo_arquivo = str_replace("mensagem_sucesso_inserir_valor", $guarda_dados->mensagem_sucesso_inserir, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("mensagem_erro_inserir_valor", $guarda_dados->mensagem_erro_inserir, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("mensagem_sucesso_alterar_valor", $guarda_dados->mensagem_sucesso_alterar, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("mensagem_erro_alterar_valor", $guarda_dados->mensagem_erro_alterar, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("mensagem_sucesso_excluir_valor", $guarda_dados->mensagem_sucesso_excluir, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("mensagem_erro_excluir_valor", $guarda_dados->mensagem_erro_excluir, $conteudo_arquivo);
			
			// A partir daqui precisa de funções auxiliares para ajudar a substituir os valores
			$conteudo_arquivo = str_replace("mensagens_erro_campos", $this->gera_mensagens_erro_campos($guarda_dados), $conteudo_arquivo);
			$conteudo_arquivo = str_replace("campos_valores_default_valor", $this->gera_campos_valores_default($guarda_dados), $conteudo_arquivo);
			$conteudo_arquivo = str_replace("campos_paginas_valor", $this->gera_campos_paginas($guarda_dados), $conteudo_arquivo);
			$conteudo_arquivo = str_replace("campos_multiplos_valor", $this->gera_campos_multiplos($guarda_dados), $conteudo_arquivo);
			$conteudo_arquivo = str_replace("tabelas_excluir_valor", $this->gera_tabelas_excluir($guarda_dados), $conteudo_arquivo);
			
			// Parte de campos que podem ter valores pré-definidos
			$selects = "";
			$checkboxes = "";
			$radios = "";
			$this->gera_campos_varios_valores($guarda_dados, $selects, $checkboxes, $radios); // coloca as strings de substituição
			$conteudo_arquivo = str_replace("campos_select_valor", $selects, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("campos_checkbox_valor", $checkboxes, $conteudo_arquivo);
			$conteudo_arquivo = str_replace("campos_radio_valor", $radios, $conteudo_arquivo);
			
			
			// Salvo o conteudo modificado do arquivo gera_dados.php no arquivo dados.php da entidade
			$this->salva_template("dados.php", $conteudo_arquivo);
		}
		
		public function atualiza_menu_adm($guarda_dados)
		{
			// Adiciona um link no menu da adm para o gerenciar desse novo viale
			$path = dirname(__FILE__)."/../menu/adm/layoutUp.php";
			FileController::substitui_palavra($path, '</ul>', '<li><a href="../'.$guarda_dados->tabela.'/">'.$guarda_dados->tabela."</a></li>\n</ul>");
		}
		
		public function atualiza_menu_site($nome_pagina)
		{
			// Adiciona um link no menu da adm para o gerenciar desse novo viale
			$path = dirname(__FILE__)."/../menu/site/layoutUp.php";
			$nome_pagina_sem_sufixo = str_replace(".php", "", $nome_pagina);
			FileController::substitui_palavra($path, '</ul>', 
				'<?php if(file_exists("./'.$nome_pagina.'")):?>
					<li><a href="./'.$nome_pagina.'">'.$nome_pagina_sem_sufixo."</a></li>
					<?php endif; ?>
					\n</ul>");
		}
		
		public function deleta_menu($tabela_menu)
		{
			$path = dirname(__FILE__)."/../menu/adm/layoutUp.php";
			FileController::substitui_palavra($path, '<li><a href="../'.$tabela_menu.'/">'.$tabela_menu.'</a></li>', '');
		}
		
		private function valida_dados($guarda_dados, $post)
		{
			$campos_label = array('nome_entidade' => 'nome real', 'sufixo' => 'sufixo', 'referencia' => 'referência',
									'limit' => 'limite', 'range' => 'range', 'offset_default' => 'offset inicial');
			$this->erros = array();
			foreach($campos_label as $field => $label)
			{
				if($field == 'limit' || $field == 'range' || $field == 'offset_default') // validação numérica
				{
					if(!is_numeric($post[$field]))
					{
						$this->erros[$field] = "O campo $label deve ser um número";
					}
				}
				else if(empty($post[$field]))
				{
					$this->erros[$field] = "O campo $label não pode estar vazio";
				}
			}
			return empty($this->erros); // Retorna true se não ocorreu erros e validou, se não retornará false
		}
		
		private function redireciona_index()
		{
			$session = new Session();
			$session->set_session_msg(SUCESSO, "O viale da tabela $this->tabela_atual foi criado com sucesso");
			if(empty($this->erros)) header('Location: ./');
		}
		
		// Controla o formulário de criação de página de index.php
		public function cria_pagina($post)
		{
			extract($post);
			$sufixo = ".php";
			if(substr_compare($nome_pagina, $sufixo, -strlen($sufixo), strlen($sufixo)) != 0) // Se não termina com .php
			{
				$nome_pagina .= $sufixo;
			}
			
			$dest = dirname(__FILE__).'/../'.$nome_pagina;
			if(!file_exists($dest))
			{
				// Copia o conteudo de modelo.php para o caminho para anova página
				$source = dirname(__FILE__)."/../modelo.php";
				copy($source, $dest); // Copia o conteudo de $source para o arquivo $dest
				
				// Atualiza o que está escrito na página
				$nome_pagina_sem_sufixo = str_replace(".php", "", $nome_pagina);
				FileController::substitui_palavra($dest, '$area = "Modelo"', '$area = "'.$nome_pagina_sem_sufixo.'"');
			}
			
			if($login_obrigatorio != "login_obrigatorio") // Se não estiver marcado
			{
				// Comenta a linha que verifica se o usuário está logado
				FileController::substitui_palavra($dest, '$site->login->esta_logado', '// $site->login->esta_logado');
			}
			
			if($adicionar_menu == "adicionar_menu") // Se estiver marcado
			{
				$this->atualiza_menu_site($nome_pagina);
			}
			
			return "Página criada com sucesso";
		}
		
		// Controla a página criar_viale.php
		public function cria_viale($post)
		{
			if($post)
			{
				$guarda_dados = GuardaDados::getInstance();
				$this->set_dados_gerais($guarda_dados, $post); // Manda guardar os dados do post na instancia de GuardaDados
				// Se não ocorreu erro de validação, então gera o viale
				if($this->valida_dados($guarda_dados, $post))
				{
					$this->copia_diretorio($guarda_dados); // Copia o diretorio chamado viale para o novo diretorio da entidade
					// Gera o arquivo dados.php responsável pela configuração do viale
					$this->gera_dados($guarda_dados);
					$this->atualiza_menu_adm($guarda_dados);
					$this->redireciona_index();
				}
			}
			// Se o array POST não foi mandado, retorna o valor null, indicando isso
			return null;
		}
	}
?>